package com.esb.transport.protocal;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Future<T> {
	private final Lock                            lock 		= new ReentrantLock();
    private final Condition                       done 		= lock.newCondition();
    private final long                   		  id;
    private volatile T                   		  message;
    private final int                             timeout;
    private volatile Callable<Long>           	  callback;
    
    public Future(long id, Callable<Long> callable) {
		this(id, callable, 1000);
	}
    
    public Future(long id, Callable<Long> callable, int timeout) {
		this.id = id;
		this.timeout = timeout;
		this.callback = callable;
	}

	public T get(){
		long start = System.currentTimeMillis();
		lock.lock();
        try {
        	while(message==null){
        		if (System.currentTimeMillis() - start > timeout) {
        			break;
                }
        		done.await(timeout, TimeUnit.MILLISECONDS);
        	}
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
        	if(message==null && callback!=null)callback.call(id);
            lock.unlock();
        }
        return message;
	}
	
	public void set(T msg) {
        lock.lock();
        try {
        	message = msg;
            done.signal();
        } finally {
            lock.unlock();
        }
    }
}
